package com.university.mentalhealthplatform.config;

import com.university.mentalhealthplatform.global.rbac.model.*;
import com.university.mentalhealthplatform.global.rbac.repository.*;
import com.university.mentalhealthplatform.global.rbac.service.entity.BaseUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import org.yaml.snakeyaml.Yaml;
import org.springframework.transaction.annotation.Transactional;

import java.io.InputStream;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

@Component
public class DataInitializer implements CommandLineRunner {

    @Autowired
    private MenuRepository menuRepository;

    @Autowired
    private ButtonComponentRepository buttonComponentRepository;

    @Autowired
    private EndpointRepository endpointRepository;

    @Autowired
    private PermissionRepository permissionRepository;

    @Autowired
    private RoleRepository roleRepository;

    @Autowired
    private BaseUserRepository baseUserRepository;

    @Autowired
    private BaseUserService baseUserService;

    @Override
    @Transactional
    public void run(String... args) throws Exception {
        InputStream inputStream = getClass().getResourceAsStream("/application.yml");
        Yaml yaml = new Yaml();
        Map<String, Object> config = yaml.load(inputStream);

        // 解析并插入各类数据
        insertPermissions((List<Map<String, Object>>) ((Map<String, Object>) config.get("app")).get("permissions"));
        insertMenus((List<Map<String, Object>>) ((Map<String, Object>) config.get("app")).get("menus"), null);
        insertEndpoints((List<Map<String, Object>>) ((Map<String, Object>) config.get("app")).get("endpoints"));
        insertButtonComponents((List<Map<String, Object>>) ((Map<String, Object>) config.get("app")).get("buttonComponents"));

        // 插入默认角色和用户
        Role defaultRole = insertDefaultRole();
        createDefaultUser(defaultRole);
    }

    private void insertPermissions(List<Map<String, Object>> permissions) {
        for (Map<String, Object> permissionConfig : permissions) {
            String identifier = (String) permissionConfig.get("identifier");
            permissionRepository.findByIdentifier(identifier).ifPresentOrElse(
                    permission -> {},
                    () -> {
                        Permission permission = new Permission();
                        permission.setIdentifier(identifier);
                        permission.setDisplayName((String) permissionConfig.get("displayName"));
                        permission.setStatus((Boolean) permissionConfig.get("status"));
                        permission.setOrderNum((Integer) permissionConfig.get("orderNum"));
                        permissionRepository.save(permission);
                    }
            );
        }
    }

    private void insertButtonComponents(List<Map<String, Object>> buttonComponents) {
        for (Map<String, Object> buttonConfig : buttonComponents) {
            String identifier = (String) buttonConfig.get("identifier");

            // 查找是否已经存在按钮组件
            buttonComponentRepository.findByIdentifier(identifier).ifPresentOrElse(
                    button -> {},
                    () -> {
                        ButtonComponent button = new ButtonComponent();
                        button.setIdentifier(identifier);
                        button.setDisplayName((String) buttonConfig.get("displayName"));
                        button.setDescription((String) buttonConfig.get("description"));
                        button.setVisible((Boolean) buttonConfig.get("visible"));
                        button.setStatus((Boolean) buttonConfig.get("status"));
                        button.setOrderNum((Integer) buttonConfig.get("orderNum"));

                        // 设置父菜单
                        String parentMenuIdentifier = (String) buttonConfig.get("parentMenu");
                        menuRepository.findByIdentifier(parentMenuIdentifier).ifPresent(button::setParentMenu);

                        // 关联按钮组件的 endpoint
                        if (buttonConfig.containsKey("endpoints")) {
                            List<String> endpoints = (List<String>) buttonConfig.get("endpoints");
                            for (String endpoint : endpoints) {
                                endpointRepository.findByIdentifier(endpoint).ifPresent(button.getEndpoints()::add);
                            }
                        }

                        buttonComponentRepository.save(button);
                    }
            );
        }
    }


    private void insertMenus(List<Map<String, Object>> menus, Menu parent) {
        for (Map<String, Object> menuConfig : menus) {
            String identifier = (String) menuConfig.get("identifier");
            menuRepository.findByIdentifier(identifier).ifPresentOrElse(
                    menu -> {},
                    () -> {
                        Menu menu = new Menu();
                        menu.setIdentifier(identifier);
                        menu.setDisplayName((String) menuConfig.get("name"));
                        menu.setUrl((String) menuConfig.get("path"));
                        menu.setOrderNum((Integer) menuConfig.get("orderNum"));
                        menu.setParentMenu(parent);

                        menuRepository.save(menu);

                        // 插入子菜单
                        if (menuConfig.containsKey("children")) {
                            insertMenus((List<Map<String, Object>>) menuConfig.get("children"), menu);
                        }
                    }
            );
        }
    }

    private void insertEndpoints(List<Map<String, Object>> endpoints) {
        for (Map<String, Object> endpointConfig : endpoints) {
            String identifier = (String) endpointConfig.get("identifier");
            endpointRepository.findByIdentifier(identifier).ifPresentOrElse(
                    endpoint -> {},
                    () -> {
                        Endpoint endpoint = new Endpoint();
                        endpoint.setIdentifier(identifier);
                        endpoint.setPath((String) endpointConfig.get("path"));
                        endpoint.setMethod((String) endpointConfig.get("method"));
                        endpoint.setAccessLevel(AccessLevel.valueOf((String) endpointConfig.get("accessLevel")));
                        endpoint.setAllowAnonymous((Boolean) endpointConfig.get("allowAnonymous"));

                        // 设置权限
                        if (endpointConfig.containsKey("requiredPermissions")) {
                            List<String> requiredPermissions = (List<String>) endpointConfig.get("requiredPermissions");
                            for (String permissionIdentifier : requiredPermissions) {
                                permissionRepository.findByIdentifier(permissionIdentifier)
                                        .ifPresent(endpoint.getPermissions()::add);
                            }
                        }

                        endpointRepository.save(endpoint);
                    }
            );
        }
    }

    private Role insertDefaultRole() {
        String roleId = "ROLE_SUPERADMIN";
        return roleRepository.findByIdentifier(roleId).orElseGet(() -> {
            Role defaultRole = new Role();
            defaultRole.setIdentifier(roleId);
            defaultRole.setDisplayName("超级管理员");

            // 绑定所有权限和菜单
            defaultRole.setPermissions(new HashSet<>(permissionRepository.findAll()));
            defaultRole.setMenus(new HashSet<>(menuRepository.findAll()));

            roleRepository.save(defaultRole);
            return defaultRole;
        });
    }

    private void createDefaultUser(Role defaultRole) {
        String username = "SuperAdmin";
        baseUserRepository.findByUsername(username).ifPresentOrElse(
                user -> {},
                () -> {
                    User user = baseUserService.createUserIfNotFound(username, "123456");
                    user.getRoles().add(defaultRole);
                    baseUserRepository.save(user);
                }
        );
    }
}
